using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System;
using System.Threading;
using System.Text;
using System.IO;
using System.Collections.Generic;

/// <summary>
/// UI界面的基类，定义了统一的UI功能接口(事件，开关，动画，声音...)。
/// </summary>
public abstract class BaseUI : MonoBehaviour
{
    //当前的UI模块对象
    public GameObject mWndObject = null;
    public GameObject WndObject { get { return mWndObject; } }
    public EnumUIType[] _uiHistoryList = new EnumUIType[2];
    public GameObject loadingPanel = null;

    #region 缓存对象和 transfrom        Cache gameObject & transfrom

    // 缓存 Transform
    private Transform _CachedTransform;

    /// <summary>
    /// 缓存 Transform 属性
    /// </summary>
    /// <value>The cached transform.</value>                                   
    public Transform cachedTransform
    {
        get
        {
            if (!_CachedTransform)
            {
                _CachedTransform = this.transform;
            }
            return _CachedTransform;
        }
    }

    // 缓存 对象
    private GameObject _CachedGameObject;

    /// <summary>
    /// 缓存 对象   属性
    /// </summary>
    /// <value>The cached game object.</value>
    public GameObject cachedGameObject
    {
        get
        {
            if (!_CachedGameObject)
            {
                _CachedGameObject = this.gameObject;
            }
            return _CachedGameObject;
        }
    }

    #endregion

    protected virtual void SetUI(Dictionary<EnumUIType, object> uiParams)
    {
        
    }

    /// <summary>
    /// 获得UI模块下的UI对象
    /// </summary>
    /// <param name="name">UI对象的名称</param>
    /// <returns></returns>
    public GameObject Control(string name)
    {
        if (mWndObject == null)
            return null;

        return Control(name, mWndObject);
    }

    /// <summary>
    /// 获得UI模块下的UI对象,重载的主函数
    /// </summary>
    /// <param name="name">UI对象的名称</param>
    /// <param name="parent">根对象</param>
    /// <returns></returns>
    public GameObject Control(string name, GameObject parent)
    {
        Transform[] children = parent.GetComponentsInChildren<Transform>(true);
        for (int i=0;i<children.Length;i++) {
            if (children[i].name == name)
                return children[i].gameObject;
        }
        return null;
    }

    //public T FindComponent<T>(string path)
    //{
    //    T v = mWndObject.transform.Find(path).GetComponent<T>();
    //    return v;
    //}

    //public static void Request(ServiceEnum serviceName, string uid, RequestParamBean param, MainScript.MessageBodyDelegate del)
    //{
    //    MainScript.Instance.SendAndReceive(MainScript.Instance.GetMessageRequest(serviceName, uid, param), del);
    //}


    #region UI对象的类型和状态     UIType & EnumObjectState

    /// <summary>
    /// UI对象的状态
    /// </summary>
    protected EnumObjectState state = EnumObjectState.None;

    /// <summary>
    /// UI对象的状态的 访问器，属性，状态改变时会发布事件
    /// </summary>
    /// <value>The state.</value>
    //public EnumObjectState State
    //{
    //          protected set                         // 继承的类可以访问protected成员，但是不能访问private成员。
    //	{
    //		if (value != state)                  //　如果新的状态与旧的状态不相同
    //		{
    //			EnumObjectState oldState = state;　　　　// 存储旧的状态
    //			state = value;                           // 存储新的状态
    //                  if (null != StateChanged)                // 如果已经有人注册了 StateChanged 事件
    //			{
    //				StateChanged(this, state, oldState);    // 发布事件
    //			}
    //		}
    //	}
    //	get { return this.state; }
    //}

    //在外面赋值的时候就会触发属性方法
    public EnumObjectState State
    {
        protected set
        {
            if (value != state)
            {
                EnumObjectState oldState = state;
                state = value;
                if (null != StateChanged)
                {
                    StateChanged(this, state, oldState);
                }
            }
        }
        get { return this.state; }
    }


    /// <summary>
    /// 对象状态改变的事件
    /// </summary>
    public event StateChangedEvent StateChanged;

    /// <summary>
    /// 声明一个 返回值为EnumUIType的抽象方法，在子类中去实现
    /// </summary>
    /// <returns>The user interface type.</returns>
    public abstract EnumUIType GetUIType();      // 一个类中，只要有一个抽象方法，这个类必须被声明为抽象类（抽象类不能被继承）。
    // 抽象方法在子类中必须被重写。

    #endregion



    /// <summary>
    /// UI层级置顶
    /// </summary>
    protected virtual void SetDepthToTop()
    {

    }


    /// <summary>
    /// 调用OnStart方法，建议UI中用OnStart来实现以前在Start里实现的功能
    /// </summary>
    void Start()
    {
        OnStart();
       
    }


    /// <summary>
    /// 状态为初始化的时候，调用OnAwake方法
    /// </summary>
    void Awake()
    {
        this.State = EnumObjectState.Initial;
        //屏蔽所有debug.log
        //Debug.unityLogger.logEnabled = false;
        OnAwake();


    }


    ///// <summary>
    ///// 状态为准备好的时候，调用OnUpdate方法
    ///// </summary>
    //void Update()
    //{
    //    if (EnumObjectState.Ready == this.state)
    //    {
    //        OnUpdate(Time.deltaTime);
    //    }
    //}

    /// <summary>
    /// 释放UI对象的方法
    /// </summary>
    public void Release()
    {
        this.State = EnumObjectState.Closing;    // 状态为关闭时，销毁缓存的对象，并调用OnRelease方法
        
        GameObject.Destroy(cachedGameObject);
        OnRelease();
    }
    GameObject _uiAnimCanvas;//部分ui界面打开时候的动画所在的canvas
    //IEnumerator OpenUIAnimEtor(EnumUIType uiType)
    public void OpenUIAnimEtor()
    {
        //if (uiType == EnumUIType.EquipmentUIWnd)
        //{
        
        UnityEngine.Object _uiAnimprefab= Resources.Load("Prefabs/OpenUIAnim");//部分ui界面动画的预制体;//部分ui界面动画的预制体
        GameObject _uiAnimObj = null;

            if (_uiAnimCanvas != null)
            {
                _uiAnimObj = MonoBehaviour.Instantiate(_uiAnimprefab, _uiAnimCanvas.transform) as GameObject;
                //float _x1 = _uiAnimObj.transform.localPosition.x + 1650;
                _uiAnimObj.transform.localPosition = Vector3.zero;
            }
            else
            {
                _uiAnimCanvas = GameObject.Find("Canvas2");
                _uiAnimObj = MonoBehaviour.Instantiate(_uiAnimprefab, _uiAnimCanvas.transform) as GameObject;

                _uiAnimObj.transform.localPosition = Vector3.zero;

            }
       // }
        //yield return -1;
    }

    /// <summary>
    /// 子类中，建议UI中用OnStart来实现以前在Start里实现的功能
    /// </summary>
    protected virtual void OnStart()
    {

    }

    /// <summary>
    /// 子类中，建议UI中用OnAwake来实现以前在Awake里实现的功能
    /// </summary>
    protected virtual void OnAwake()
    {
        this.State = EnumObjectState.Loading;     // 状态为加载时，播放音乐;
        //播放音乐
        this.OnPlayOpenUIAudio();
        

    }

    ///// <summary>
    ///// 子类中，建议UI中用OnUpdate来实现以前在Update里实现的功能
    ///// </summary>
    //protected virtual void OnUpdate(float deltaTime)
    //{

    //}

    /// <summary>
    /// OnRelease方法，关闭界面音乐
    /// </summary>
    protected virtual void OnRelease()
    {
        this.OnPlayCloseUIAudio();
    }


    /// <summary>
    /// 播放打开界面音乐（通用的打开音乐可以写在基类里面，特定的写在子类里）
    /// </summary>
    protected virtual void OnPlayOpenUIAudio()
    {
        
    }

    /// <summary>
    /// 播放关闭界面音乐（通用的关闭音乐可以写在基类里面）
    /// </summary>
    protected virtual void OnPlayCloseUIAudio()
    {

    }

    #region 通用音效播放
    /// <summary>
    /// 按钮点击
    /// </summary>
    protected void Audio_DianJi()
    {
        //Debug.Log("  按钮点击  音效    ");
        AudioController.Instance.SoundPlay(AudioPlayerName.tyandj, 0.7f);
    }

    /// <summary>
    /// 界面打开
    /// </summary>
    protected void Audio_WndOpen()
    {
        //Debug.Log("  界面打开  音效    ");
        //AudioController.Instance.SoundPlay(AudioPlayerName.jm_dakai, 0.8f);
    }
    /// <summary>
    /// 界面关闭
    /// </summary>
   

    #endregion

    #region 查找场景内的子物体
    public GameObject GetchildObj(string name, GameObject parent)
    {
        Transform[] children = parent.GetComponentsInChildren<Transform>(true);
        for (int i = 0; i < children.Length; i++)
        {
            if (children[i].name == name)
                return children[i].gameObject;
        }
        return null;
    }
    #endregion

    /// <summary>
    /// 在打开UI的时候，在UIManaget里面会通过 SetUI来把 UIInfoData 里的可变参数传递给打开的UI对象
    /// 当需要传递多个参数，或参数个数不定的时候，就可以用params类型的参数。
    /// params类型的参数搭配数组使用，实现一个不定长的数组参数
    /// </summary>
    /// <param name="uiParams"></param>
    protected virtual void SetUI(params object[] uiParams)
    {
        this.State = EnumObjectState.Loading;
    }


    public virtual void SetUIparam(params object[] uiParams)
    {

    }

    /// <summary>
    /// 在子类里面重写
    /// 打开UI对象时加载数据的逻辑
    /// </summary>
    protected virtual void OnLoadData()
    {

    }

    /// <summary>
    /// 在打开UI的时候，在UIManaget里面会通过 SetUI来把 UIInfoData 里的可变参数传递给打开的UI对象
    /// SetUI里面，当界面打开的时候，我们会加载数据，用异步加载，只需要重写OnLoadData()就能实现加载数据的逻辑
    /// </summary>
    /// <param name="uiParams"></param>
    // 修改方法签名，直接接收一个 Dictionary<EnumUIType, object>
    public void SetUIWhenOpening(Dictionary<EnumUIType, object> uiParams)
    {
        //Debug.Log("baseui.SetUIWhenOpening:" + (uiParams != null ? uiParams.Count : 0));
        // 直接调用 SetUI，传递字典参数
        if(null != uiParams)
            SetUI(uiParams);
        //CoroutineController.Instance.StartCoroutine(AsyncOnLoadData());
    }

    /// <summary>
    /// 协成实现打开UI对象时加载数据的逻辑，OnLoadData()方法可以在子类里面重写，进行一些数据操作和一些界面上的操作
    /// </summary>
    /// <returns></returns>
    private IEnumerator AsyncOnLoadData()
    {
        yield return new WaitForSeconds(0);
        if (this.State == EnumObjectState.Loading)//当状态为加载的状态
        {
            this.OnLoadData();//打开UI对象时加载数据的逻辑
            this.State = EnumObjectState.Ready;//状态为准备好
        }
    }
}


